package org.grayrabbit.cms.plugin.util;

import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class LastModifiedHandler {
	private long lastModified;
	private String etag;
	private static final int ONE_SECOND_MILLIS = 1000;

	public LastModifiedHandler() {
		modified(new Date());
	}

	public LastModifiedHandler(Date lastModifiedDate) {
		modified(lastModifiedDate);
	}

	public boolean checkRequest(HttpServletRequest request,
			HttpServletResponse response) {
		return checkRequest(request, response, this.lastModified, this.etag);
	}

	public void modified() {
		modified(new Date());
	}

	private void modified(Date date) {
		this.lastModified = calculateLastModifiedDate(date);
		this.etag = calculateEtag(this.lastModified);
	}

	private static long calculateLastModifiedDate(Date lastModifiedDate) {
		long lastModified = lastModifiedDate.getTime();
		lastModified -= lastModified % ONE_SECOND_MILLIS;
		return lastModified;
	}

	private static String calculateEtag(long lastModified) {
		return "\"" + lastModified + "\"";
	}

	public static boolean checkRequest(HttpServletRequest request,
			HttpServletResponse response, Date lastModifiedDate) {
		long lastModified = calculateLastModifiedDate(lastModifiedDate);
		return checkRequest(request, response, lastModified,calculateEtag(lastModified));
	}

	private static boolean checkRequest(HttpServletRequest request,
			HttpServletResponse response, long lastModified, String etagString) {
		if ("true".equals(System.getProperty("cms.disable.caches","false"))) {
			return false;
		}
		response.setDateHeader("Last-Modified", lastModified);
		response.setHeader("ETag", etagString);
		long ifModifiedSince = request.getDateHeader("If-Modified-Since");
		String ifNoneMatch = request.getHeader("If-None-Match");
		if ((noConditionalGetHeadersFound(ifModifiedSince, ifNoneMatch))
				|| (isContentModifiedSince(ifModifiedSince, lastModified))
				|| (!etagMatches(ifNoneMatch, etagString))) {
			return false;
		}
		response.setStatus(304);
		return true;
	}

	private static boolean etagMatches(String ifNoneMatch, String etagString) {
		return (ifNoneMatch != null) && (ifNoneMatch.equals(etagString));
	}

	private static boolean isContentModifiedSince(long ifModifiedSince,
			long lastModified) {
		return (ifModifiedSince != -1L) && (ifModifiedSince < lastModified);
	}

	private static boolean noConditionalGetHeadersFound(long ifModifiedSince,
			String ifNoneMatch) {
		return (ifModifiedSince == -1L) && (ifNoneMatch == null);
	}
}
